
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace Swaf.FtpServer
{
	/// <summary>
	/// Summary description for FtpServer.
	/// </summary>
	public class FtpServer
	{
		protected FtpConfigPartner m_serverMgr;
		protected IList m_bizRuleHandlers = new ArrayList();
		protected bool m_continueWorking = true;
		protected string m_ip, m_baseDirectory;
		protected int m_port;
		protected Thread m_workThread;

		protected TcpListener m_socketServer;
		protected long m_idleTimeOut = 20000;
		protected int m_maxLineLength = 500;
		protected int m_maxBadCmds = 5;

		public FtpServer(FtpConfigPartner serverMgr, string ip, string port, string baseDirectory)
		{
			m_serverMgr = serverMgr;
			m_ip = ip;
			m_port = Int32.Parse(port);
			m_baseDirectory = baseDirectory;
		}

		public void start()
		{
			m_workThread = new Thread(new ThreadStart(processFtpClientConnections));
#if(!COMPACT_FRAMEWORK)
			m_workThread.IsBackground = true;
#endif
			m_workThread.Start();
		}

		public void stop()
		{
			m_socketServer.Stop();
			m_continueWorking = false;
			m_workThread.Interrupt();
		}

		public bool isClientAllowedToConnect(EndPoint clientAddress)
		{
			bool isIt = true;

			//TODO: Add support to have list of valid ip or list of invalid ip

			return isIt;
		}

		public long IdleTimeOut
		{
			get{return m_idleTimeOut;}
			set{m_idleTimeOut = value;}
		}

		public int MaxLineLength
		{
			get{return m_maxLineLength;}
			set{m_maxLineLength = value;}
		}

		public int MaxBadCommands
		{
			get{return m_maxBadCmds;}
			set{m_maxBadCmds = value;}
		}

		public string IpAddress {get{return m_ip;}}
		public int Port {get{return m_port;}}
		public string BaseDirectory {get{return m_baseDirectory;}}

		internal void defineBizRuleHandler(string ruleName, string filePattern, bool fileIn)
		{
			m_bizRuleHandlers.Add(new BizRuleHandler(ruleName, filePattern, fileIn));
		}

		internal string getBizRuleHandler(string fileName, bool fileIn)
		{
			IApplication app = Application.globalApp;

			foreach(BizRuleHandler handler in m_bizRuleHandlers)
			{
				try
				{
					if(app.resMgr.matches(handler.FilePattern, fileName).Success && handler.FileIn == fileIn)
						return handler.RuleName;
				}
				catch(Exception e)
				{
					//TODO: Log exception....
					//TODO: Pull out bad BizRuleHandler element
				}
			}
			return null;
		}
	
		internal void sessionEnded(FtpSession clientSession)
		{
			m_serverMgr.removeSession(clientSession);
		}

		protected void processFtpClientConnections()
		{
			try
			{
				if(String.Compare(m_ip, "all", true) == 0)
					m_socketServer = new TcpListener(IPAddress.Any, m_port);
				else
					m_socketServer = new TcpListener(IPAddress.Parse(m_ip), m_port);

				m_socketServer.Start();
				while(m_continueWorking)
				{
					try
					{
						FtpSession clientSession = new FtpSession(this, m_socketServer.AcceptSocket());
						m_serverMgr.addSession(clientSession);
					}
					catch
					{
					}
				}

			}
			catch(Exception e)
			{
				string em = e.Message;
			}
		}

		protected class BizRuleHandler
		{
			public string RuleName, FilePattern;
			public bool FileIn;

			public BizRuleHandler(string ruleName, string filePattern, bool fileIn)
			{
				RuleName = ruleName;
				FilePattern = filePattern;
				FileIn = fileIn;
			}
		}
	}
}
